import context from './context';
import sql from './sql';
const http = require('http');
let data_update_version; //远程数据库日期
let data_last_version;   //更新触发时的日期

//test ping
(function () {
    http.request({
        host: "www.baidu.com",
        method: 'GET',
    }, function (res) {
        res.setEncoding('utf8');
        // console.log('STATUS: ' + res.statusCode);
        // console.log('HEADERS: ' + JSON.stringify(res.headers));
        res.on('data', data => {
            console.log("ContextServer.testping", 'testping', String(data).substring(0, 100));
        })

    }).on('error', function (e) {
        console.log("ContextServer.testping", 'testping http错误', e.message);
    }).end();
})();


//拉取远端数据库
//@param isInit 是否初始化更新  (如果是初始化更新，更新出错后返回3  如果不是则则返回4)  如果不是初始化则出错返回4
//@callback  由ContextServer.checkUpdate 一路继承来  2更新成功 3更新失败(需要重启) 4更新失败(可以忽略)
function pullDatas(isInit, callback) {
    console.log("ContextServer.pullDatas", 'im pullDatas');
    //依次拉取 version、(enger、affix、load)
    //拉完数据先存起来，统一进行更新操作
    let engrDatas = [], affixDatas = [], weightDatas = [], loadDatas = [], roleDatas = [], bossDatas = [], weapDatas = [];

    let updateSql = () => {
        try {
            /* 更新版本信息 */
            {
                //记录远端版本
                sql.updateAppdatasByName({
                    'name': 'data_update_version',
                    'value': data_update_version
                })

                //记录更新时间
                sql.updateAppdatasByName({
                    'name': 'data_last_version',
                    'value': data_last_version
                });
            }

            sql.initUpdateEngrs(engrDatas);
            sql.initUpdateAffixs(affixDatas);
            sql.initUpdateWeights(weightDatas);
            sql.initUpdateLoads(loadDatas);
            sql.initUpdateRoles(roleDatas);
            sql.initUpdateBoss(bossDatas);
            sql.initUpdateWeaps(weapDatas);

        } catch (error) {
            console.log("ContextServer.pullDatas", "更新数据已解析，更新数据库出错");
            console.log(error);

            //重置一个较早的日期 保证开启程序后一定能触发更新
            sql.updateAppdatasByName({
                'name': 'data_update_version',
                'value': '1990-01-01'
            })

            //如果出错 只能让前端重启
            callback && callback({
                code: 3,
                message: error.message,
                title: `${context.app_version} ___ 更新错误...`
            })
            return;
        }

        //更新结束 前端恢复操作
        callback && callback({
            code: 2,
            message: '',
            title: `${context.app_version} ___ 数据库版本${data_update_version}`,
        })
    }

    let pullLoads = () => {
        //@TODO
        //暂无  直接返回
        console.log("ContextServer.pullDatas", '跳过loads更新');
        updateSql();

        //throw new Error("pullLoads http error:" + e.message)
    }

    let pullMyDatas = () => {
        http.request({
            host: context.config['server_host'],
            path: context.config['check_data_url'] + "?tm=" + sql.generateUUID(),
            method: 'GET'
        }, function (res) {
            // console.log('STATUS: ' + res.statusCode);
            // console.log('HEADERS: ' + JSON.stringify(res.headers));
            //长数据可多次触发data事件 用datas拼接每段数据
            let datas = "";

            res.setEncoding('utf8');
            res.on('data', data => {
                datas += data;
            });
            res.on('end', () => {
                let object = JSON.parse(datas);

                if (!object) {
                    console.log("ContextServer.pullDatas", "pullMyDats,没有拉取到object数据");
                    throw new Error("没有拉取到object数据");
                    return;
                }

                // console.log("拉取datas, engrs", JSON.stringify(object.engrs).substring(0, 20));
                // console.log("拉取datas, affixs", JSON.stringify(object.affixs).substring(0, 20));
                // console.log("拉取datas, weights", JSON.stringify(object.weights).substring(0, 20));

                if (object.engrs) {
                    engrDatas = object.engrs
                } else {
                    console.log("ContextServer.pullDatas", "pullMyDats,没有拉取到object.engrs数据");
                    throw new Error("没有拉取到object.engrs数据");
                }

                if (object.affixs) {
                    affixDatas = object.affixs
                } else {
                    console.log("ContextServer.pullDatas", "pullMyDats,没有拉取到object.affixs数据");
                    throw new Error("没有拉取到object.engrs数据");
                }

                if (object.weights) {
                    weightDatas = object.weights
                } else {
                    console.log("ContextServer.pullDatas", "pullMyDats,没有拉取到object.weights数据");
                    throw new Error("没有拉取到object.weights数据");
                }
                if (object.roles) {
                    roleDatas = object.roles
                } else {
                    console.log("ContextServer.pullDatas", "pullMyDats,没有拉取到object.roles数据");
                    throw new Error("没有拉取到object.roles数据");
                }

                if (object.boss) {
                    bossDatas = object.boss
                } else {
                    console.log("ContextServer.pullDatas", "pullMyDats,没有拉取到object.boss数据");
                    throw new Error("没有拉取到object.boss数据");
                }

                if (object.weaps) {
                    weapDatas = object.weaps
                } else {
                    console.log("ContextServer.pullDatas", "pullMyDats,没有拉取到object.weaps数据");
                    throw new Error("没有拉取到object.weaps数据");
                }
                pullLoads();
            })

        }).on('error', function (e) {
            console.log("ContextServer.pullDatas", 'pullMyDatas http错误', error.message);
            throw new Error("pullMyDatas http error:" + e.message)
        }).end();
    }

    let pullVersion = () => {

        http.request({
            host: context.config['server_host'],
            path: context.config['check_version_url']+ "?tm=" + sql.generateUUID(),
            method: 'GET'
        }, function (res) {
            // console.log('STATUS: ' + res.statusCode);
            // console.log('HEADERS: ' + JSON.stringify(res.headers));
            res.setEncoding('utf8');
            res.on('data', function (data) {
                //收到数据
                let object = JSON.parse(data);

                if (!object) {
                    console.log("ContextServer.pullDatas", "pullVersion,没有拉取到数据")
                    throw new Error("没有拉取到版本信息")
                }

                data_update_version = object['data_update_version'];
                data_last_version = sql.getCurrentData();

                pullMyDatas();
            });
        }).on('error', function (e) {
            console.log("ContextServer.pullDatas", 'pullVersion http错误: ' + e.message);
            throw new Error("pullVersion http error:" + e.message)
        }).end();
    }

    try {
        pullVersion();
    } catch (error) {
        console.log("ContextServer.pullDatas", "更新错误", error);
        callback && callback({
            code: isInit ? 3 : 4,
            message: '没有拉取到版本数据',
            title: isInit ? `${context.app_version} ___ 更新错误...` : `${context.app_version} ___ 数据库版本${sql.queryVersion()}`,
        });
    }
}

//本地版本和远程版本对比
//@retrun code 0无需更新 1需要更新
function checkServerVersion(locVersion, callback) {
    console.log("ContextServer.checkServerVersion",context)

    http.request({
        host: context.config['server_host'],
        path: context.config['check_version_url'] + "?tm=" + sql.generateUUID(),
        method: 'GET'
    }, function (res) {
        // console.log('STATUS: ' + res.statusCode);
        // console.log('HEADERS: ' + JSON.stringify(res.headers));
        res.setEncoding('utf8');
        res.on('data', function (data) {
            //收到数据
            let object = JSON.parse(data);
            let result = object['data_update_version']
            let flag = object['force_update_when_checked']; //强制更新参数

            /* 是否强制更新数据 */
            // if (flag) {
            //     console.log("ContextServer.checkServerVersion", "强制更新");
            //     callback && callback({
            //         code: 1,
            //         message: 'http success',
            //         title: `${context.app_version} ___ 正在更新中...`,
            //     });
            //     pullDatas(true, callback);
            //     return;
            // }

            /* 一般情况下对比日期  远程版本高时更新*/
            let locDate = new Date(locVersion);
            let ServDate = new Date(result);

            console.log("ContextServer.checkServerVersion", "locVersion", locVersion);
            console.log("ContextServer.checkServerVersion", "servVersion", result);

            if (ServDate > locDate) {
                console.log("远端version高", locDate, ServDate);

                //发送更新消息
                callback && callback({
                    code: 1,
                    message: 'http success',
                    title: `${context.app_version} ___ 正在更新中...`,
                });
                pullDatas(false, callback);

            } else {
                //发送检查结束消息
                console.log("ContextServer.checkServerVersion", "无需更新");
                callback && callback({
                    code: 0,
                    message: 'http success',
                    title: `${context.app_version} ___ 数据库版本${locVersion}`,
                });
            }
        });
    }).on('error', function (e) {
        console.log("ContextServer.checkServerVersion", "http error", e.message);
        callback && callback({
            code: 4,
            message: 'http error',
            title: `${context.app_version} ___ 数据库版本${locVersion}`,
        });
    }).end();
}

/* 更新模块 */
const ContextServer = {

    getLocalDataVersion(){
        let sqlrs = sql.queryVersion()
        return sqlrs.value
    },

    clearDatabase(){
        return new Promise(resolve=>{
            sql.clearDatabase()

            // 必须等待3秒以上 给lokijs写入时间
            setTimeout(e=>resolve(),3000)
        })
    },

    getServerDataVersion(){
        return new Promise((resolve,rej)=>{
            http.request({
                host: context.config['server_host'],
                path: context.config['check_version_url'] + "?tm=" + sql.generateUUID(),
                method: 'GET'
            }, function (res) {
                res.setEncoding('utf8');
                res.on('data', function (data) {
                    let obj = JSON.parse(data)
                    // console.log("getServerDataVersion",obj)
                    resolve(obj['data_update_version']) //@return
                });
            }).on('error', function (e) {
                console.log("ContextServer.checkServerVersion", "http error", e.message);
                rej()
            }).end();
        })
    },

    //异步方法 用win.webContents回复消息
    //@callback 调用页面回调
    //@callback ->objct  {code: message: title}   code 0无需更新 1等待更新 2更新成功 3更新失败(需要重启) 4更新失败(可以忽略)
    checkUpdate(callback) {
        console.log('ContextServer.checkUpdate');
        // testping();

        //读取本地version
        let sqlrs = sql.queryVersion()
        if (!sqlrs) {
            //没有查询到信息(可能是第一次运行)
            //直接拉数据
            console.log("没找到本地version信息")
            pullDatas(true, callback);

            //发送更新消息
            callback && callback({
                code: 1,
                message: 'http success',
                title: `${context.app_version} ___ 正在更新中...`,
            });
            return;
        }

        //对比远程版本
        checkServerVersion(sqlrs.value, callback);
    },

    //检查app端是否有更新
    checkAppPcUpdate(){
        let current = context.app_version;

        return new Promise((resolve,rej)=>{
            http.request({
                host: context.config['server_host'],
                path: context.config['check_app_ver_url'] + "?tm=" + sql.generateUUID(),
                method: 'GET'
            }, function (res) {
                res.setEncoding('utf8');
                res.on('data', function (data) {
                    console.log("checkAppPcUpdate data",data)
                    try{
                        let obj = JSON.parse(data)
                        let ver = obj['pc_version']
                        resolve( ver == current) //@return
                    }catch(e){
                        rej(e)
                    }
                });
            }).on('error', function (e) {
                console.log("ContextServer.checkAppPcUpdate", "http error", e.message);
                rej(e)
            }).end();
        })
    }
}

/* 刻印查询模块 */
const SearchServer = {

    // 所有刻印名字和图标
    queryAllNames() {
        // console.info("queryAllNames")
        let sqlrs = sql.queryAllEngrNames();
        let list = sqlrs.map(element => {
            return {
                name: element.name,
                icon: element.icon,
                type: element.type,
            }
        });
        return list;
    },

    // 查询刻印
    query(data) {
        console.info("query条件查询", data);
        let sqlrs = sql.queryEngr(data.name || null, data.location || null, data.param || null, data.res || null);
        // console.log("查询刻印结果：",sqlrs);
        return sqlrs;
    },

    queryEngrById(data) {
        // console.info("queryEngrById");
        let sqlrs = sql.queryEngrById(data.id);
        return sqlrs[0];
    },

    queryAllAffixs() {
        // console.info("queryAllAffixs");
        let sqlrs = sql.queryAllAffixs();
        return sqlrs;
    }
}

/* 刻印搭配模块 */
const CalcServer = {

    //@callback(code)  0成功 1失败
    addFavorited(data) {
        //data.name, data.list, data.count, data.mark, data.weightId, data.weightName
        if (!data.id || data.id == '') {
            return {
                code: 1,
                message: "id不能为空"
            }
        }

        
        if (!data.name || data.name == "") {
            return {
                code: 1,
                message: "收藏名不能为空"
            }
        }

        if (!data.list || data.list == "") {
            return {
                code: 1,
                message: "排列表不能为空"
            }
        }

        if (!data.count || data.count == "") {
            return {
                code: 1,
                message: "词条表不能为空"
            }
        }

        //防止lokijs监听该对象，克隆一份
        let object = JSON.parse(JSON.stringify(data));

        //去除冗余字段
        delete object.compared;
        delete object.favorited;
        delete object.index;
        delete object.$loki;
        delete object.meta;

        object.list.forEach(e => {
            e.effect = '';
            e.icon = '';
            e.type = '';
        })

        object.list = JSON.stringify(object.list);
        object.count = JSON.stringify(object.count);

        // console.log('CalcServer.addFavorited 准备插入对象', object);
        sql.insertFavorited(object);

        //原始对象的favorited设为true
        data.favorited = true;

        return {
            code: 0
        }
    },

    //@callback(code)  0成功 1失败
    removeFavorited(data) {
        if (!data || !data.id) {
            return {
                code: 1,
                message: "id不能为空"
            }
        }

        if (sql.removeFavoritedById(data.id)) {
            return {
                code: 0
            }
        } else {
            return {
                code: 1,
                message: "删除失败"
            }
        }
    },

    removeAllFavorited() {
        sql.clearFavorited();
    },

    queryAllFavorites() {
        let sqlrs = sql.queryAllFavorited();

        //防止lokijs监听到对象改动，直接克隆一份对象
        let datas = JSON.parse(JSON.stringify(sqlrs));
        datas.forEach(e => {
            e.count = JSON.parse(e.count);
            e.list = JSON.parse(e.list).map(e1 => {
                let engr = sql.queryEngrById(e1.id)
                return engr;
            });

            e.compared = false; //需要处理下;
            e.favorited = true;
        });
        // console.log("CalcServer.queryAllFavorites", datas);
        return datas;
    },

    queryAllWeightsName() {
        return sql.queryAllWeightsName().map(e => ({
            name: e.name,
            id: e.id,
        }));
    },

    queryWeightsById(id) {
        return sql.queryWeightsById(id);
    },

    removeWeightsById(id) {

    },

    removeCustomWeights(id){
        sql.removeCustomWeights()
    },

    insertWeights(data) {
        // console.log("CalcServer.insertWeights", data);
        sql.insertWeights(data);
    },
}

/* 角色速查模块 */
const LoadServer = {

}

/* 配队模块*/
const TeamServer = {
    queryAllRoles() {
        let sqlrs = sql.queryAllRoles();
        let rs =  JSON.parse(JSON.stringify(sqlrs))
        rs.forEach(e => {
            delete e.$loki;
            delete e.meta;
        })

        return rs;
    },

    queryAllBoss() {
        let sqlrs = sql.queryAllBoss();
        let rs =  JSON.parse(JSON.stringify(sqlrs))

        rs.forEach(e => {
            delete e.$loki;
            delete e.meta;
        })
        return rs;
    },

    queryBossOptions() {
        let datas = TeamServer.queryAllBoss();
    },

    getNewScheme() {
        return {
            id: sql.generateUUID(),
            name: '',
            remark: '',
            box: [],
            used: [], //记录梦境用过的角色
            dream_team: [],
            free_team: [],
        }
    },

    getNewTeam() {
        return {
            id: sql.generateUUID(),
            name: "",
            priority: "",
            boss: "",
            remark: "",
            data: [
                this.getNewTeamRole(),
                this.getNewTeamRole(),
                this.getNewTeamRole(),
            ]
        }
    },

    getNewTeamRole(){
        return {
            role_id: 0,         //角色id
            role_name: "",       //角色名字
            role_icon: "",       //角色图标
            role_class: "",       //角色阵营

            weap_id: 0,         //权钥id
            weap_name: "",       //权钥名字
            weap_icon: "",       //权钥图标

            engrs: [                 //6个刻印
                {}, {}, {}, {}, {}, {},
            ],
            gods: [                  //3个神格
                {}, {}, {}
            ],
        }
    },

    queryAllSchemeNames() {
        let sqlrs = sql.queryAllTeams();
        return sqlrs.map(e => ({
            id: e.id,
            name: e.name
        }));
    },

    queryScheme(id) {
        return sql.queryTeamsById(id);
    },

    saveScheme(scheme, roles) {
        //先删除旧方案
        if (sql.removeTeamsById(scheme.id)) {
            // console.log("server.TeamServer.saveScheme", "删除旧数据")
        }

        let copy = JSON.parse(JSON.stringify(scheme));
        copy.box = roles.map(e => e.id);
        // console.log("插入teams库", copy);

        sql.insertTeams(copy);
        return true;
    },

    removeScheme(id) {
        sql.removeTeamsById(id);
    },

    queryAllWeaps() {
        let sqlrs = sql.queryAllWeaps();

        let rs1 = sqlrs.filter(e => e.exclusive != ""); //专武
        let rs2 = sqlrs.filter(e => e.rank == 5 && e.exclusive == ""); //五星通用
        let rs3 = sqlrs.filter(e => e.rank == 4) //四星通用
        let rs4 = sqlrs.filter(e => e.rank == 3) //三星通用

        return rs1.concat(rs2).concat(rs3).concat(rs4);
    },

    //根据玩家选择的刻印组合补全词条
    queryEngrGroupByTeamEngrs(datas) {
        let result = {
            id: sql.generateUUID(),
            favorited: false,
            compared: false,
            index: 0,
            name: '角色刻印',
            mark: "~",
            remark: "",
            weightId: "",
            weightName: "",
            count: {},
            list: JSON.parse(JSON.stringify(datas)),
        }

        //补全刻印信息
        result.list = result.list.map((e, i) => {
            return e.name ? sql.queryEngr(e.name, i+1)[0] : e;
        });

        //统计词条
        result.list.forEach(e => {
            if (e.name) {
                let affix1 = e.affix1;
                let affix2 = e.affix2;

                if (result.count[affix1]) {
                    result.count[affix1] += 1;
                } else {
                    result.count[affix1] = 1;
                }

                if (result.count[affix2]) {
                    result.count[affix2] += 1;
                } else {
                    result.count[affix2] = 1;
                }
            }
        });

        return result;
    }
}

export { ContextServer, SearchServer, CalcServer, LoadServer, TeamServer }